package vk
{
  import flash.events.TimerEvent;
  import flash.utils.ByteArray;
  import flash.utils.Timer;
  import PrivateVars.vk;
  import Tools.Debug;
  import vk.Api;

  /**
   * ...
   * @author Roman Marchenko
   */
  public class RemoteVars
  {
    static public const RADIO_HISTORY:String = "radio_history";
    static public const LASTFM_LOGIN:String = "lastfm_login";
    static public const LASTFM_SESKEY:String = "lastfm_sk";
    static public const SCROBBLING_ENABLED:String = "scrobbling_enabled";

    static private var testMode:uint;
    static private var _storage:Object = {radio_history: "", lastfm_login: "", lastfm_sk: "", scrobbling_enabled: "1", uint_value: "", string_value: ""};
    static private var _inProgress:Boolean = false;
    static private var _onOk:Function = null;
    static private var _onError:Function = null;
    static private var _putQueue:Array = new Array;

    static public function load(onOk:Function = null, onError:Function = null):void
    {
      if (_inProgress)
      {
        throw 1;
      }

      _inProgress = true;
      var keys:String = "";
      for (var name:String in _storage)
      {
        if ("" != keys)
        {
          keys += ","
        }
        keys += name;
      }

      trace("RemoteVars.load: " + keys);
      _onOk = onOk;
      _onError = onError;
      getVars(keys);
    }

    static private function onGetKeysOk(data:Object):void
    {
      Debug.log("RemoteVars.onGetOk");
      for (var i:int = 0; i < data.length; ++i)
      {
        if ("" != data[i].value)
        {
          _storage[data[i].key] = data[i].value;
        }
      }

      if (null != _onOk)
      {
        _onOk();
      }
      _onOk = null;
      _onError = null;
      _inProgress = false;
    }

    static private function onGetKeysError(data:Object):void
    {
      Debug.log("RemoteVars.onGetError");
      if (null != _onError)
      {
        _onError();
      }
      _onOk = null;
      _onError = null;
      _inProgress = false;
    }

    static private function onPutError(data:Object):void
    {
      var obj:Object = _putQueue.shift();
      Debug.log("RemoteVars.onPutError: " + obj.key);
      if (null == data)
      {
        throw 1; // Error, shouldn't be.
        return;
      }

      //var e:RemoteVarsEvent;
      if (!data.hasOwnProperty("error_code"))
      {
        // Some connection errors?..
        if (obj.onError)
        {
          obj.onError(obj.key, obj.value);
        }
        return;
      }

      switch (int(data.error_code))
      {
        case 6:
          Debug.log("RemoteVars.onPutError: too many requests per second");
          var onTimer:Function = function(e:TimerEvent):void
        {
          Debug.log("RemoteVars.onPutError: trying to put after timeout...");
          vk.RemoteVars.putVarNext();
        }
          var t:Timer = new Timer(1000, 1);
          t.addEventListener(TimerEvent.TIMER, onTimer);
          t.start();
          break;

        default:
          // unexpected
          if (obj.onError)
          {
            obj.onError(obj.key, obj.value);
          }
          break;
      }
    }

    static public function getVar(key:String):String
    {
      if (null == _storage[key])
      {
        trace("RemoteVars.getVar: unknown variable " + key);
        throw 1;
      }

      return _storage[key];
    }

    static private function getVars(keys:String):void
    {
      var VK:Api = new Api;
      VK.api('storage.get', {test_mode: testMode, keys: keys}, onGetKeysOk, onGetKeysError);
    }

    static private function onPutOk(data:Object):void
    {
      var obj:Object = _putQueue.shift();
      Debug.log("RemoteVars.onPutOk: " + obj.key);
      if (obj.onOk)
      {
        obj.onOk(obj.key, obj.value);
      }

      if (0 < _putQueue.length)
      {
        putVarNext();
      }
      else
      {
        _inProgress = false;
      }
    }

    static private function putVarNext():void
    {
      var obj:Object = _putQueue[0];
      Debug.log("RemoteVars.putVarNext: " + obj.key + "=" + obj.value + ", total vars: " + _putQueue.length);
      var VK:Api = new Api;
      VK.api('storage.set', {test_mode: testMode, key: obj.key, value: obj.value}, onPutOk, onPutError);
    }

    static public function putVar(key:String, value:String, onOk:Function = null, onError:Function = null):void
    {
      if (null == _storage[key])
      {
        throw 1;
      }
      _storage[key] = value;
      _putQueue.push({key: key, value: value, onOk: onOk, onError: onError});
      Debug.log("RemoteVars.putVar: " + key + ", total vars: " + _putQueue.length);
      if (!_inProgress)
      {
        _inProgress = true;
        putVarNext();
      }
    }
  }

}